import 'dart:io';

import 'package:path_provider/path_provider.dart';

///
/// [getTemporaryDirectory]
/// 临时目录，适用于下载的缓存文件，此目录随时可以清除，此目录为应用程序私有目录，其他应用程序无法访问此目录
/// `Android` 上对应 [getCacheDir]，`iOS` 上对应 [NSCachesDirectory] 
/// 
/// [getApplicationDocumentsDirectory]
/// 应用程序可能在其中放置用户生成的数据或应用程序无法重新创建的数据的目录路径
/// `Android` 上对应 [getDataDirectory]，`iOS` 上对应 [NSDocumentDirectory] 
/// 
/// [getApplicationSupportDirectory]
/// 应用程序可以在其中放置应用程序支持文件的目录的路径
/// `Android` 上对应 [getFilesDir]，`iOS` 上对应 [NSApplicationSupportDirectory] 
/// 

enum CacheMethod {
  temporary,
  documents,
  support,
}

// ignore_for_file: unnecessary_null_comparison
class CacheManager {

  /// 创建 `path_provider` 单一实例
  CacheManager._internal();
  static CacheManager? _singleton;
  static CacheManager instance() {
    // 如果 `_singleton` 为空则 `_singleton == CacheManager._internal()`
    _singleton ??= CacheManager._internal();
    return _singleton!;
  }

  /// 格式化缓存大小
  static String cacheSize() {

    double value = double.parse(total().toString());
    if (value == null) {
      return '0 B';
    }
    List<String> unit = [' B', ' K', ' M', ' G',];
    int index = 0;
    while (value > 1024) {
      index ++;
      value = value / 1024;
    }
    String size = value.toStringAsFixed(2);
    return size + unit[index];
  }

  /// 获取缓存大小
  static Future<int> total({CacheMethod method = CacheMethod.temporary}) async {

    Directory? tempDir;
    if (method == CacheMethod.temporary) {
        tempDir = await getTemporaryDirectory();
    } else if (method == CacheMethod.documents) {
        tempDir = await getApplicationDocumentsDirectory();
    } else if (method == CacheMethod.support) {
        tempDir = await getApplicationSupportDirectory();
    }

    if (tempDir == null) return 0;
    int total = await _reduce(tempDir);
    return total;
  }
  
  /// 递归缓存目录，计算缓存大小
  /// [file] 文件或文件目录
  static Future<int> _reduce(final FileSystemEntity file) async {
    
    // 如果是一个文件夹则直接返回文件大小
    if (file is File) {
      int length = await file.length();
      return length;
    }

    // 如果是目录则遍历目录并累计大小
    if (file is Directory) {
      final List<FileSystemEntity> children = file.listSync();
      int total = 0;
      if (children != null && children.isNotEmpty) {
        for (final FileSystemEntity child in children) {
          total += await _reduce(child);
        }
      }
      return total;
    }
    return 0;
  }

  /// 清除缓存
  static Future<void> clear({CacheMethod method = CacheMethod.temporary}) async {

    Directory? tempDir;
    if (method == CacheMethod.temporary) {
        tempDir = await getTemporaryDirectory();
    } else if (method == CacheMethod.documents) {
        tempDir = await getApplicationDocumentsDirectory();
    } else if (method == CacheMethod.support) {
        tempDir = await getApplicationSupportDirectory();
    }

    if (tempDir == null) return;
    await _delete(tempDir);
  }

  /// 递归删除缓存目录及文件
  /// [file] 文件或文件目录
  static Future<void> _delete(FileSystemEntity file) async {

    // 如果是目录则递归目录删除文件及文件夹
    // 如果不是目录是文件则直接删除文件
    if (file is Directory) {
      final List<FileSystemEntity> children = file.listSync();
      for (final FileSystemEntity child in children) {
        await _delete(child);
      }
    } 
    // else {
    //   await file.delete();
    // }
    await file.delete();
  }
}